/**********************************************************************************
Program:       chinaweathergadget

License:       GNU/GPL version 3

File:          Form_EditCityList.cs

Description:   绘制编辑城市列表的弹出窗体

Author:        Guangyu Liu （lgy0417@gmail.com）

Environment:   .NET Framework v2.0 or later version

Usage/Example: README_chs.txt

Last Modified: 2010.08.30

***********************************************************************************/


using System;
using System.Drawing;
using System.Resources;
using System.Reflection;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using WeatherInfo;
using PrettifiedControls.PrettifiedButton;
using PrettifiedControls.PrettifiedListBox;


namespace GUI
{
	public class EditCitiesForm : Form      // 此窗体在主窗体“编辑”按钮按下时弹出
	{
		#region Declaration
		private Label titleLabel;
		private ListBoxNew cities_ListBox;
		private ButtonNew add;
		private ButtonNew delete;
		private ButtonNew edit;
		private ButtonNew up;
		private ButtonNew down;
		private ButtonNew ok;
		private ButtonNew cancel;
		private int indexOfSource;         //拖动的起始索引
        private int indexOfTarget;         //拖动的结束索引
		private List<SingleCity> cbuList;
		private List<SingleCity> currentList;
		private ID_Database idd;
		private CityListChangedDelegate clcd;
		private ResourceManager rm;
		#endregion
		
		public EditCitiesForm(List<SingleCity> cbuList, ID_Database idd, CityListChangedDelegate clcd)
		{
			this.cbuList = cbuList;
			this.clcd = clcd;
			this.idd = idd;
			this.rm = new ResourceManager("ChinaWeatherGadget", Assembly.GetExecutingAssembly());
			currentList = new List<SingleCity>();
			foreach (SingleCity i in cbuList)
				currentList.Add(i);         // 副本，深拷贝
			InitializeComponents();
		}
		
		private void InitializeComponents()
		{
			#region TitleLabel
			titleLabel = new Label();
			titleLabel.Text = "城市名称列表：";
			titleLabel.AutoSize = true;
			titleLabel.Left = 30;
			titleLabel.Top = 20;
			this.Controls.Add(titleLabel);
			#endregion

			#region Buttons
			int buttonWidth = 55;
			int buttonHeight = 24;
			int buttonLeft = 320;
			int buttonSpace = 20;
			int imageWidth = 15;
	
			add = new ButtonNew();
			add.Text = "添加";
			add.Width = buttonWidth;
			add.Height = buttonHeight;
			add.Location = new Point(buttonLeft, titleLabel.Bottom + 5);
			add.Image = (Image)rm.GetObject("add_png");
			add.ImageWidth = imageWidth;
			add.TextImageRelation = TextImageRelation.ImageBeforeText;
			this.Controls.Add(add);
			
			delete = new ButtonNew();
			delete.Text = "删除";
			delete.Width = buttonWidth;
			delete.Height = buttonHeight;
			delete.Location = new Point(buttonLeft, add.Bottom + buttonSpace);
			delete.Image = (Image)rm.GetObject("delete_png");
			delete.ImageWidth = imageWidth;
			delete.TextImageRelation = TextImageRelation.ImageBeforeText;
			this.Controls.Add(delete);
			
			edit = new ButtonNew();
			edit.Text = "编辑";
			edit.Width = buttonWidth;
			edit.Height = buttonHeight;
			edit.Location = new Point(buttonLeft, delete.Bottom + buttonSpace);
			edit.Image = (Image)rm.GetObject("edit_png");
			edit.ImageWidth = imageWidth;
			edit.TextImageRelation = TextImageRelation.ImageBeforeText;
			this.Controls.Add(edit);
			
			up = new ButtonNew();
			up.Text = "上移";
			up.Width = buttonWidth;
			up.Height = buttonHeight;
			up.Location = new Point(buttonLeft, edit.Bottom + buttonSpace);
			up.Image = (Image)rm.GetObject("up_png");
			up.ImageWidth = imageWidth;
			up.TextImageRelation = TextImageRelation.ImageBeforeText;
			this.Controls.Add(up);
			
			down = new ButtonNew();
			down.Text = "下移";
			down.Width = buttonWidth;
			down.Height = buttonHeight;
			down.Location = new Point(buttonLeft, up.Bottom + buttonSpace);
			down.Image = (Image)rm.GetObject("down_png");
			down.ImageWidth = imageWidth;
			down.TextImageRelation = TextImageRelation.ImageBeforeText;
			this.Controls.Add(down);
			
			ok = new ButtonNew();
			ok.Text = "确定";
			ok.Width = buttonWidth;
			ok.Height = buttonHeight;
			ok.Location = new Point(buttonLeft, down.Bottom + buttonSpace);
			ok.Image = (Image)rm.GetObject("ok_png");
			ok.ImageWidth = imageWidth;
			ok.TextImageRelation = TextImageRelation.ImageBeforeText;
			this.Controls.Add(ok);

			cancel = new ButtonNew();
			cancel.Text = "取消";
			cancel.Width = buttonWidth;
			cancel.Height = buttonHeight;
			cancel.Location = new Point(buttonLeft - 80, ok.Top);
			cancel.Image = (Image)rm.GetObject("cancel_png");
			cancel.ImageWidth = imageWidth;
			cancel.TextImageRelation = TextImageRelation.ImageBeforeText;
			this.Controls.Add(cancel);
			#endregion

			#region ListBox
			cities_ListBox = new ListBoxNew();
			cities_ListBox.Location = new Point(titleLabel.Left, add.Top);
			cities_ListBox.Width = 260;
			cities_ListBox.Height = down.Bottom - add.Top + 10;
			cities_ListBox.RowBackColor1 = Color.FromArgb(226, 234, 255);
			cities_ListBox.RowBackColor2 = Color.White;
			cities_ListBox.SelectedColor = Color.FromArgb(253, 183, 89);
			cities_ListBox.ItemHeight = 25;
			cities_ListBox.AllowDrop = true;
			cities_ListBox.TabIndex = 0;
			this.Controls.Add(cities_ListBox);

			cities_ListBox.BeginUpdate();
			for (int x = 0; x < cbuList.Count; x++)
			{
				string fullName = idd.GetTownFullName(cbuList[x]);
				cities_ListBox.Items.Add(new ListBoxNewItem(fullName));
			}
			cities_ListBox.EndUpdate();
			#endregion

			#region form
			this.StartPosition = FormStartPosition.CenterParent;
			this.MaximizeBox = false;
			this.Opacity = 0.96;
			this.BackColor = Color.FromArgb(224,234,247);
			this.ClientSize = new Size(buttonLeft + buttonWidth + 30, ok.Bottom + 30);
			this.FormBorderStyle = FormBorderStyle.FixedSingle;
			this.Text = "编辑自选城市列表";
			this.Icon = (Icon)rm.GetObject("16x16_icon");
			this.ShowInTaskbar = false;
			#endregion
			
			#region events declaration
			
			add.Click += new System.EventHandler(this.buttonAdd_Click);
			delete.Click += new System.EventHandler(this.buttonDelete_Click);
			edit.Click += new System.EventHandler(this.buttonEdit_Click);
			up.Click += new System.EventHandler(this.buttonUp_Click);
			down.Click += new System.EventHandler(this.buttonDown_Click);
			ok.Click += new System.EventHandler(this.buttonOK_Click);
			cancel.Click += new System.EventHandler(this.buttonCancel_Click);
			
			cities_ListBox.MouseDoubleClick += new MouseEventHandler(this.ListBox_MouseDoubleClick);
			
			// 下面三个注册用于 cities_ListBox 中的鼠标拖拽操作
			cities_ListBox.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ListBox_MouseDown);
            cities_ListBox.DragOver += new System.Windows.Forms.DragEventHandler(this.ListBox_DragOver);
            cities_ListBox.DragDrop += new System.Windows.Forms.DragEventHandler(this.ListBox_DragDrop);

			#endregion
		}
		
		#region event-handler functions
		
		private void buttonAdd_Click(object sender, System.EventArgs e)
		{
			AddOrEditOneCityDelegate aoeocd = new AddOrEditOneCityDelegate(AddOrEditOneCity);
			AddOrEditOneCityForm add_Form = new AddOrEditOneCityForm(idd, aoeocd);
			add_Form.ShowDialog();
		}
		
		private void buttonEdit_Click(object sender, System.EventArgs e)
		{
			if(cities_ListBox.SelectedIndex != -1)
			{
				// 把被编辑的项的 SingleCity 结构体传入
				AddOrEditOneCityDelegate aoeocd = new AddOrEditOneCityDelegate(AddOrEditOneCity);
				AddOrEditOneCityForm add_Form = new AddOrEditOneCityForm(idd, aoeocd, currentList[cities_ListBox.SelectedIndex]);
				add_Form.ShowDialog();
			}
		}
		
		private void AddOrEditOneCity(SingleCity city, bool isAdding)
		{
			// 此函数的委托随子窗体的构造函数传入子窗体，并在子窗体的“确定”按钮被按下的事件中调用
			// 如果有选中项就插在选中项之前，否则放在第一位
			string nameInListBox = idd.GetTownFullName(city);
			for (int i = 0; i < currentList.Count; i++)
			{
				if (currentList[i].Equals(city))
				{
					MessageBox.Show(nameInListBox + "  已经在列表中，不能重复添加！", 
								"警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
					if (isAdding)
						cities_ListBox.SelectedIndex = i;
					return;
				}
			}
			int index = cities_ListBox.SelectedIndex == -1 ? 0 : cities_ListBox.SelectedIndex;
			if (!isAdding)
			{
				cities_ListBox.Items.RemoveAt(index);
				currentList.RemoveAt(index);
			}
			cities_ListBox.Items.Insert(index, new ListBoxNewItem(nameInListBox));
			currentList.Insert(index, city);
		}
		
		private void buttonDelete_Click(object sender, System.EventArgs e)
		{
			if(cities_ListBox.Items.Count == 1)
				MessageBox.Show("请勿将所有城市全部移除！", 
								"警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
			else if(cities_ListBox.SelectedIndex != -1)
			{
				int index = cities_ListBox.SelectedIndex;
				cities_ListBox.Items.RemoveAt(index);
				currentList.RemoveAt(index);
			}
		}
		
		private void buttonUp_Click(object sender, System.EventArgs e)
		{
			//若不是第一行则与上面的交换
            if (cities_ListBox.SelectedIndex > 0)
            {
                int index = cities_ListBox.SelectedIndex;
                ListBoxNewItem temp = cities_ListBox.Items[index - 1];
                cities_ListBox.Items[index - 1] = cities_ListBox.Items[index]; 
                cities_ListBox.Items[index] = temp;
                cities_ListBox.SelectedIndex = index - 1;
				SingleCity tmp = currentList[index - 1];
				currentList[index - 1] = currentList[index];
				currentList[index] = tmp;
            }
		}
		
		private void buttonDown_Click(object sender, System.EventArgs e)
		{
			//若不是最后一行则与下面的交换
			if (cities_ListBox.SelectedIndex > -1 && cities_ListBox.SelectedIndex < cities_ListBox.Items.Count - 1)
			{
				int index = cities_ListBox.SelectedIndex;
				ListBoxNewItem temp = cities_ListBox.Items[index + 1];
				cities_ListBox.Items[index + 1] = cities_ListBox.Items[index]; 
				cities_ListBox.Items[index] = temp;
				cities_ListBox.SelectedIndex = index + 1;
				SingleCity tmp = currentList[index + 1];
				currentList[index + 1] = currentList[index];
				currentList[index] = tmp;
			}
		}
		
		private void buttonOK_Click(object sender, System.EventArgs e)
		{
			// 修改完毕，回调父窗体中的 CityNameListModified 函数
			if (currentList.Count != cbuList.Count)
				clcd(currentList);
			else
				for (int i = 0; i < currentList.Count; i++)
					if (currentList[i].CityID != cbuList[i].CityID)
						clcd(currentList);
			this.Close();
		}
		
		private void buttonCancel_Click(object sender, System.EventArgs e)
		{
			this.Close();
		}
		
		private void ListBox_MouseDoubleClick(object sender, MouseEventArgs e)
		{
			if (cities_ListBox.SelectedIndex != -1)
            {
				Rectangle rec= cities_ListBox.GetItemRectangle(cities_ListBox.SelectedIndex);
				if (e.X > rec.Left && e.X < rec.Right &&
					e.Y > rec.Top  && e.Y < rec.Bottom)
					buttonEdit_Click(null, null);
			}
		}
		#endregion
		
		#region 以下三个函数用于描述编辑城市列表时的拖拽操作
		private void ListBox_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if (e.Clicks ==1)  // 此条件使得双击事件与拖拽操作的 MouseDown 事件不冲突
			{
				indexOfSource = ((ListBoxNew)sender).IndexFromPoint(e.X, e.Y);
				if (indexOfSource != ListBoxNew.NoMatches)
					((ListBoxNew)sender).DoDragDrop(((ListBoxNew)sender).Items[indexOfSource].ToString(), DragDropEffects.All);
			}
		}

		private void ListBox_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
		{
			if (e.Data.GetDataPresent(typeof(System.String)))
				e.Effect = DragDropEffects.All;
			else
				e.Effect = DragDropEffects.None;
		}

		private void ListBox_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
		{
			ListBoxNew listbox = (ListBoxNew)sender;
			indexOfTarget = listbox.IndexFromPoint(listbox.PointToClient(new Point(e.X, e.Y)));
			if (indexOfTarget == ListBox.NoMatches)
				indexOfTarget = listbox.Items.Count - 1;
			ListBoxNewItem temp = listbox.Items[indexOfSource];
			
			if (indexOfTarget > indexOfSource)   // 向下拖拽，平移中间的项目
				for(int i = indexOfSource; i != indexOfTarget; i++)
					listbox.Items[i] = listbox.Items[i+1];
			if (indexOfTarget < indexOfSource)   // 向上拖拽，平移中间的项目
				for(int i = indexOfSource; i != indexOfTarget; i--)
					listbox.Items[i] = listbox.Items[i-1];
			listbox.Items[indexOfTarget] = temp;
			listbox.SelectedIndex = indexOfTarget;
			
			SingleCity tmp = currentList[indexOfSource];
			currentList.RemoveAt(indexOfSource);
			currentList.Insert(indexOfTarget, tmp);
		}
	
		#endregion
	}
}
